home *** CD-ROM | disk | FTP | other *** search
- /*
- exe2com 1.02 - an exe2bin replacement
- by Chris Dunford/The Cove Software Group.
- see exe2com.doc for more info.
-
- usage: exe2com file [file]
- usage is the same as exe2bin except:
- 1. Output defaults to COM rather than BIN
- 2. Binary fixup option not supported
- 3. Checksum not verified
- 4. Provides more useful error messages, and a warning if a
- COM file is being created with initial IP != 0x100.
-
- Compiler notes:
- The original executable of this file was produced with the
- Computer Innovations C86 compiler (v2.2).
-
- This program was knocked together in about an hour in response to
- the removal of EXE2BIN from the standard DOS distribution disks.
- Improvements/corrections are encouraged.
-
- Program donated to the public domain by the author.
-
- cjd 4/17/87
-
- Modified to run under Turbo C by Roger Schlafly, Borland.
- (It may not run on C86 any more.)
- Compile with
- tcc -Id:\c -Ld:\c -mt -w -O -Z -p exe2com
- exe2com exe2com
- or
- tcc -Id:\c -Ld:\c -M -mt -w -DDEBUG=1 -O -Z -p exe2com
- exe2com exe2com
-
- rss 6/26/87
-
- Fix for even 512-byte boundary file losing last 512 bytes.
- Also corrected signon per request of Chris Dunford ( his name
- was lost in the translation to Turbo C ).
- Version updated to 1.02 to indicate change.
-
- Chris Blum CompuServe 76625,1041
-
- CJB 11/22/87
- */
-
- #include <stdio.h>
-
- #include <string.h>
- /* for unlink */
- #include <dos.h>
- /* for exit */
- #include <stdlib.h>
- /* for tolower */
- #include <ctype.h>
-
- /* Conversion error codes */
- #define BADREAD 1
- #define BADWRITE 2
- #define BADSIG 3
- #define HASRELO 4
- #define HAS_SS 5
- #define HAS_CS 6
- #define BAD_IP 7
- #define TOO_BIG 8
-
- /*
- ** Define structure of fixed-format part of EXE file header
- */
- struct exe_header {
- char exe_sig[2]; /* EXE file signature: "MZ" */
- unsigned excess, /* Image size mod 512 (valid bytes in last page) */
- pages, /* # 512-byte pages in image */
- relo_ct, /* Count of relocation table entries */
- hdr_size, /* Size of header, in paragraphs */
- min_mem, /* Min required memory */
- max_mem, /* Max required memory */
- ss, /* Stack seg offset in load module */
- sp, /* Initial value of SP */
- cksum, /* File checksum */
- ip, /* Initial value of IP */
- cs, /* CS offset in load module */
- relo_start, /* Offset of first relo item */
- ovl_num; /* Overlay number */
- } xh;
-
- FILE *fi, /* Input file stream */
- *fo; /* Output file stream */
-
- char fin[129], /* Input file name */
- fon[129]; /* Output file name */
-
-
- unsigned long code_start, /* Offset of program image in EXE file */
- code_size; /* Size of program image, in bytes */
-
-
- void err_xit (unsigned code);
- void convert (void);
- void read_hdr(void);
- void init (unsigned argc, char *argv[]);
-
- char *lower (char *cp)
- {
- char *cp0;
- for (cp0=cp; (*cp=tolower (*cp)) != 0; ++cp)
- ;
- return cp0;
- }
-
- void cdecl main(unsigned argc, char *argv[])
- {
- init (argc, argv);
- read_hdr ();
- convert ();
- }
-
-
- /*
- ** Initialize - get filenames and open/create files
- */
- void init (unsigned argc, char *argv[])
- {
- char *cp;
-
- printf ("exe2com 1.02 by Chris Dunford/The Cove Software Group\n");
-
- /* Check arg count */
- if (argc < 2 || argc > 3) {
- fprintf (stderr, "usage: exe2com file [file]\n");
- exit (1);
- }
-
- /* If argv[1] (the input file) has no extension, add .EXE */
- strcpy (fin, lower (argv[1]));
- if (!strchr (fin, '.'))
- strcat (fin, ".exe");
-
- /* Get or construct output file name */
- if (argc == 3)
- strcpy (fon, lower (argv[2]));
- else
- strcpy (fon, fin);
-
- /* Check output extension--change EXE to COM, or add COM */
- if (!(cp = strchr (fon, '.')))
- strcat (fon, ".com");
- else if (strcmp (cp, ".exe") == 0)
- strcpy (cp, ".com");
-
- #ifdef DEBUG
- printf ("input=%s, output=%s\n", fin, fon);
- #endif
-
- /* Try to open input file */
- if (!(fi = fopen (fin, "rb"))) {
- fprintf (stderr, "exe2com: can't find input file %s\n", fin);
- exit (1);
- }
-
- /* Try to create output file */
- if (!(fo = fopen (fon, "wb"))) {
- fprintf (stderr, "exe2com: can't open output file %s\n", fin);
- exit (1);
- }
- }
-
-
- /*
- ** Read and check the EXE file header
- */
- void read_hdr(void)
- {
-
- /* Read the formatted portion of the header */
- if (!fread (&xh, sizeof (struct exe_header), 1, fi))
- err_xit (BADREAD);
-
- #ifdef DEBUG
- printf ("EXE file header:\n");
- printf (" signature %c%c\n", xh.exe_sig[0], xh.exe_sig[1]);
- printf (" bytes last pg %04x\n", xh.excess);
- printf (" pages %04x\n", xh.pages);
- printf (" relo count %04x\n", xh.relo_ct);
- printf (" header size %04x\n", xh.hdr_size);
- printf (" min mem %04x\n", xh.min_mem);
- printf (" max mem %04x\n", xh.max_mem);
- printf (" ss %04x\n", xh.ss);
- printf (" sp %04x\n", xh.sp);
- printf (" checksum %04x\n", xh.cksum);
- printf (" ip %04x\n", xh.ip);
- printf (" cs %04x\n", xh.cs);
- printf (" relo tbl start %04x\n", xh.relo_start);
- printf (" overlay nbr %04x\n", xh.ovl_num);
- #endif
-
- /* Check header; to be convertible, must have:
- ** -- first two bytes == "MZ"
- ** -- no relocatable items
- ** -- no stack segment
- ** -- no code segment
- ** -- IP == 0 or 100
- */
- if (strncmp (xh.exe_sig, "MZ", 2))
- err_xit (BADSIG);
- if (xh.relo_ct)
- err_xit (HASRELO);
- if (xh.ss || xh.sp)
- err_xit (HAS_SS);
- if (xh.ip != 0 && xh.ip != 0x100)
- err_xit (BAD_IP);
-
- /* Compute offset of program image in module, and program size.
- **
- ** The program size is computed as follows; it cannot exceed 64K bytes:
- ** 512 * (# EXE pages - 1)
- ** + valid bytes in last EXE page
- ** - offset of program image in EXE file
- **
- ** Note that if the IP is nonzero, we will skip the first
- ** IP bytes of the program image, and copy IP bytes fewer
- ** than the actual size.
- */
- code_start = ((unsigned long) xh.hdr_size) << 4;
- code_size = (unsigned long) (xh.pages-1) * 512
- + (xh.excess ? xh.excess : 512) /* fixed 11/19/87 - CJB */
- - code_start;
- if (code_size >= 65536L)
- err_xit (TOO_BIG);
-
- /* Issue a warning if COM file and IP != 0x100 */
- if (!strcmp (strchr (fon, '.'), ".com") && xh.ip != 0x100)
- fprintf (stderr, "exe2com warning: COM file, initial IP not 100H\n");
-
- }
-
-
-
- /*
- ** Convert the file. Nothing to do, really, other than
- ** reading the image (which follows the header), and
- ** dumping it back out to disk.
- */
- void convert (void)
- {
- char buffer[512];
- unsigned wsize;
-
- /* Seek to start of program image, skipping IP bytes */
- if (fseek (fi, code_start+xh.ip, 0) != 0)
- err_xit (BADREAD);
-
- /* Reduce the "remaining" byte count by IP bytes */
- code_size -= xh.ip;
-
- /* Read blocks and copy to output */
- while (code_size) {
-
- /* Read block */
- if (!fread (buffer, 1, 512, fi))
- err_xit (BADREAD);
-
- /* Set count of bytes to write, write block */
- wsize = (unsigned) (code_size > 512 ? 512 : code_size);
- if (!fwrite (buffer, wsize, 1, fo))
- err_xit (BADWRITE);
-
- /* Subtract bytes written from remaining byte count */
- code_size -= wsize;
- }
-
- /* All done, close the two files */
- fclose (fi);
- fclose (fo);
- }
-
-
- /*
- ** Display an error message, delete output file, exit.
- */
- void err_xit (unsigned code)
- {
- char msg[64];
-
- switch (code) {
- case BADREAD: strcpy (msg, "error reading EXE header");
- break;
- case BADWRITE: strcpy (msg, "error writing output file");
- break;
- case BADSIG: strcpy (msg, "invalid EXE file signature");
- break;
- case HASRELO: strcpy (msg, "EXE has relocatable items");
- break;
- case HAS_SS: strcpy (msg, "EXE has stack segment");
- break;
- case HAS_CS: strcpy (msg, "EXE has nonzero CS");
- break;
- case BAD_IP: strcpy (msg, "IP not 0 or 100H");
- break;
- case TOO_BIG: strcpy (msg, "program exceeds 64K");
- break;
- default: strcpy (msg, "unknown error");
- }
-
- fprintf (stderr, "exe2com: %s, can't convert\n", msg);
-
- /* Close two files and delete partial output */
- fclose (fi);
- fclose (fo);
- unlink (fon);
-
- /* Exit with errorlevel 1 */
- exit (1);
- }